package a_star;
import java.util.HashSet;
import java.util.Set;

public class Node {
	//node var;
	private int x;
	private int y;
	//pixel var;
	private float x_p;
	private float y_p;
	
	private boolean start;
	private boolean end;

	private double valueG; // 시작점~사각형 이동 비용
	private double valueH; // 사각형~최종목적지 이동 비용
	private double valueF; // F=G+H
	
	private boolean obstacle; // true : 장애물

	private Map Map;
	private Set<Node> adjacencies = new HashSet<Node>(); // 주변 노드

	private Node parent; // 부모노드

	public Node(int x, int y, Map Map) {

		this.x = x;
		this.y = y;
		this.Map = Map;
		//randomAdjacent(); // 랜덤 함수 ( 추후에 빼기 )
	}
	
	public int getX() {

		return x;
	}

	public void setX(int x) {

		this.x = x;
	}

	public int getY() {

		return y;
	}

	public void setY(int y) {

		this.y = y;
	}

	public boolean isStart() {

		return start;
	}

	public void setStart(boolean start) {

		this.start = start;
	}

	public boolean isEnd() {

		return end;
	}

	public void setEnd(boolean end) {

		this.end = end;
	}

	public Set<Node> getAdjacencies() {

		return adjacencies;
	}

	public void setAdjacencies(Set<Node> adjacencies) {

		this.adjacencies = adjacencies;
	}

	public Node getParent() {

		return parent;
	}

	public void setParent(Node parent) {

		this.parent = parent;
	}

	public void calculateAdjacencies() { // 주변 노드 계산

		int top = x - 1;
		int bottom = x + 1;
		int left = y - 1;
		int right = y + 1;

		if (right < Map.getColumns()) {
			if (!isObstacle()) {
				Map.getNode(x, right).addAdjacency(this);
				this.addAdjacency(Map.getNode(x, right));
			}
		}
		
		if (bottom < Map.getRows()) {
			if (!isObstacle()) {
				Map.getNode(bottom, y).addAdjacency(this);
				this.addAdjacency(Map.getNode(bottom, y));
			}
		}
	}

	public void addAdjacency(Node square) {

		adjacencies.add(square);
	}
	
	public void removeAdjacency(Node square) {
		adjacencies.remove(square);
	}

	public double getValueF(Node goal) {

		if (isStart()) {
			return 0.0;
		}

		if(Map.getMode()==1)
			return getValueH1(goal) + getValueG();
		else
			return getValueH2(goal) + getValueG();
	}

	// mode 1 - for blind.
	public double getValueH1(Node goal) {

		if (isStart()) {
			return 0.0;
		}

		valueH = (Math.abs(x - goal.getX()) + 5*Math.abs(y - goal.getY()));
		return valueH;
	}
	
	// mode 2 - for physical disability
	public double getValueH2(Node goal) {

		if (isStart()) {
			return 0.0;
		}

		valueH = (5*Math.abs(x - goal.getX()) + Math.abs(y - goal.getY()));
		return valueH;
	}
	public double getValueG() {
		if (isStart()) {
			return 0.0;
		}

		if (valueG == 0.0) {
			valueG = 1.0 + parent.getValueG();
		}		
		return valueG;
	}

	public void randomAdjacent(){
		if (Math.random() > 0.5) {
			setObstacle(true);
		}else{
			setObstacle(false);		
		}
	}

	public boolean isObstacle() {
		return obstacle;
	}

	public void setObstacle(boolean obstacle) {
		this.obstacle = obstacle;
	}

	public float getX_p() {
		return x_p;
	}

	public void setX_p(float x_p) {
		this.x_p = x_p;
	}

	public float getY_p() {
		return y_p;
	}

	public void setY_p(float y_p) {
		this.y_p = y_p;
	}
	
	

}
